home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / OS / ODUtils / Sources / PlfmFile.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-08  |  47.9 KB  |  1,634 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        PlfmFile.cpp
  3.  
  4.     Contains:    Implmentation for PlatformFile class
  5.  
  6.     Owned by:    Vincent Lo
  7.  
  8.     Copyright:    © 1993-95 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #ifndef _ODTYPES_
  13. #include "ODTypes.h"
  14. #endif
  15.  
  16. #ifndef _PLFMFILE_
  17. #include "PlfmFile.h"
  18. #endif
  19.  
  20. #ifndef _ODMEMORY_
  21. #include "ODMemory.h"
  22. #endif
  23.  
  24. #ifndef _EXCEPT_
  25. #include "Except.h"
  26. #endif
  27.  
  28. #ifndef _ODDEBUG_
  29. #include "ODDebug.h"
  30. #endif
  31.  
  32. #ifndef _PASCLSTR_
  33. #include "PasclStr.h"
  34. #endif
  35.  
  36. #ifndef _ITEXT_
  37. #include "IText.h"
  38. #endif
  39.  
  40. #ifndef _DOCUTILS_
  41. #include "DocUtils.h"
  42. #endif
  43.  
  44. #ifndef _DLOGUTIL_
  45. #include <DlogUtil.h>
  46. #endif
  47.  
  48. #ifndef _UTILDEFS_
  49. #include "UtilDefs.h"
  50. #endif
  51.  
  52. #ifndef _TEMPOBJ_
  53. #include "TempObj.h"
  54. #endif
  55.  
  56. #ifndef _UTILERRS_
  57. #include "UtilErrs.h"
  58. #endif
  59.  
  60. #ifndef __FILES__
  61. #include <Files.h>
  62. #endif
  63.  
  64. #ifndef __FOLDERS__
  65. #include <Folders.h>
  66. #endif
  67.  
  68. #ifndef __FINDER__
  69. #include <Finder.h>
  70. #endif
  71.  
  72. #ifndef __ICONS__
  73. #include <Icons.h>
  74. #endif
  75.  
  76. #ifndef __STRING__
  77. #include <string.h>
  78. #endif
  79.  
  80. #ifndef __ERRORS__
  81. #include <Errors.h>
  82. #endif
  83.  
  84. #ifndef __TEXTUTILS__
  85. #include "TextUtils.h"
  86. #endif
  87.  
  88. #ifndef _USERSRCM_
  89. #include <UseRsrcM.h>
  90. #endif
  91.  
  92. #ifndef __TEXTUTILS__
  93. #include "TextUtils.h"
  94. #endif
  95.  
  96. #pragma segment PlatformFile
  97.  
  98. //==============================================================================
  99. // Constants
  100. //==============================================================================
  101.  
  102. const    ODSShort    kMaxFileNameSize        = 64;
  103.  
  104. #define    kFileContainerType                    'ctyp'
  105. #define    kFileContainerTypeResID                1
  106.  
  107. const ODULong    kMaxCopyBufferSize            = 32 * 1024L;
  108. const ODULong    kMinCopyBufferSize            = 512;
  109.  
  110. static const ResType            kIconType[6] = {'ICN#','icl4','icl8','ics#','ics4','ics8'};
  111. static const short                kIconSize[6] = {256,   512,   1024,  64,    128,   256   };
  112.  
  113. //==============================================================================
  114. // Scalar Types
  115. //==============================================================================
  116.  
  117. //==============================================================================
  118. // Local Classes
  119. //==============================================================================
  120.  
  121. //==============================================================================
  122. // Global Variables
  123. //==============================================================================
  124.  
  125. //==============================================================================
  126. // Function Prototype
  127. //==============================================================================
  128.  
  129. //==============================================================================
  130. // PlatformFile
  131. //==============================================================================
  132.  
  133. const ODOSType kBogusOSType = 0;    // Default type/creator value until it's read
  134.  
  135. //------------------------------------------------------------------------------
  136. // PlatformFile::PlatformFile
  137. //------------------------------------------------------------------------------
  138. PlatformFile::PlatformFile()
  139. {
  140.     fContainerType = kODNULL;
  141.     fCreator = kBogusOSType;
  142.     fFileType = kBogusOSType;
  143.     fScriptTag = smSystemScript;
  144.     
  145.     fFileSpec.vRefNum = 0;
  146.     fFileSpec.parID = 0;
  147.     fFileSpec.name[0] = 0;
  148.     fDataRefNum = 0;
  149.     fFileID = kODNoFileID;
  150.     fPermission = fsCurPerm;
  151.     fResRefNum = kODNoFileRefNum;
  152.     fResOpenStack = 0;
  153.     fNeedToClose = kODFalse;
  154.     
  155.     fVolModDate = fTimeLastChecked = 0;
  156. }
  157.  
  158. //------------------------------------------------------------------------------
  159. // PlatformFile::~PlatformFile
  160. //------------------------------------------------------------------------------
  161. PlatformFile::~PlatformFile()
  162. {
  163.     ODDisposePtr(fContainerType);
  164. }
  165.  
  166. //------------------------------------------------------------------------------
  167. // PlatformFile::Specify
  168. //------------------------------------------------------------------------------
  169. void PlatformFile::Specify(const ODFileSpec* fileSpec)
  170. {
  171.     fFileSpec = *fileSpec;
  172.     fCreator = kBogusOSType;
  173.     fFileType = kBogusOSType;
  174.     fFileID = kODNoFileID;
  175. }
  176.  
  177. void PlatformFile::SpecifyFromFile(PlatformFile* file)
  178. {
  179.     const ODFileSpec &fileSpec = file->GetFileSpec();
  180.     this->Specify(&fileSpec);
  181. }
  182.  
  183. //------------------------------------------------------------------------------
  184. // PlatformFile::SetAsciiname
  185. //------------------------------------------------------------------------------
  186. void PlatformFile::SetAsciiName(const char* asciiName)
  187. {
  188.     ODSByte pname[kMaxFileNameSize+1];
  189.     strncpy(pname,asciiName,kMaxFileNameSize);
  190.     pname[kMaxFileNameSize] = 0;
  191.     
  192.     CToPascalString(pname);
  193.     if (fFileSpec.vRefNum == 0 &&
  194.         fFileSpec.parID == 0 &&
  195.         fFileSpec.name[0] == 0)
  196.     {
  197.         FSMakeFSSpec(0, 0, (StringPtr)pname, &fFileSpec);
  198.     }
  199.     else
  200.     {
  201.         CopyPascalString(fFileSpec.name,(StringPtr)pname);
  202.     }    
  203.     this->Specify(&fFileSpec);
  204. }
  205.  
  206. //------------------------------------------------------------------------------
  207. // PlatformFile::IsLocked
  208. //------------------------------------------------------------------------------
  209. ODBoolean PlatformFile::IsLocked()
  210. {
  211.     CInfoPBRec    pbBlock;
  212.     ODBoolean    result = kODFalse;
  213.  
  214.     // Check to see whether the volume is locked
  215.  
  216.     // Eric's original code with slight modifications.
  217.     // Appears to be needed in the case of a locked floppy. -TÇ
  218.     HParamBlockRec pb;
  219.     pb.volumeParam.ioCompletion = kODNULL;
  220.     pb.volumeParam.ioNamePtr = kODNULL;
  221.     pb.volumeParam.ioVRefNum = fFileSpec.vRefNum;
  222.     pb.volumeParam.ioVolIndex = 0;
  223.  
  224.     THROW_IF_ERROR(PBHGetVInfoSync(&pb));
  225.  
  226.     // <eeh> I have no clue if this "0x80"is right!!!  Find out what
  227.     // the constant is for write-access possible....
  228.  
  229.     result = (pb.volumeParam.ioVAtrb & 0x80) ? kODTrue : kODFalse;
  230.  
  231.     // Check to see whether the directory is locked
  232.     if (result == kODFalse) {
  233.         // first assume it is a file share volume
  234.         HParamBlockRec    paramBlk;
  235.         paramBlk.accessParam.ioCompletion = kODNULL;
  236.         paramBlk.accessParam.ioNamePtr = kODNULL;
  237.         paramBlk.accessParam.ioVRefNum = fFileSpec.vRefNum;
  238.         paramBlk.accessParam.ioDirID = fFileSpec.parID;
  239.         paramBlk.accessParam.ioACAccess = 0;
  240.         OSErr err = PBHGetDirAccessSync(¶mBlk);
  241.         
  242.         if (err == noErr) {        /* it is a file share volume, look at the access right */
  243.             if ((paramBlk.accessParam.ioACAccess & 0x04000000) == 0) /* no write access */
  244.                 result = kODTrue;
  245.         }
  246.         else if (err == paramErr) { /* it is not file share, look at directory */
  247.             pbBlock.dirInfo.ioCompletion = kODNULL;
  248.             pbBlock.dirInfo.ioNamePtr = kODNULL;
  249.             pbBlock.dirInfo.ioVRefNum = fFileSpec.vRefNum;
  250.             pbBlock.dirInfo.ioFDirIndex = -1;
  251.             pbBlock.dirInfo.ioDrDirID = fFileSpec.parID;
  252.             pbBlock.dirInfo.ioFlAttrib = 0;
  253.             THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  254.             if (pbBlock.dirInfo.ioFlAttrib & 1)
  255.                 result = kODTrue;
  256.         }
  257.         else
  258.             THROW(err);
  259.     }
  260.  
  261.     // Check to see whether the file is locked
  262.     if (result == kODFalse) {    
  263.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  264.         pbBlock.hFileInfo.ioFDirIndex = 0;
  265.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  266.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  267.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  268.         
  269.         THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  270.  
  271.         if (pbBlock.hFileInfo.ioFlAttrib & 1)
  272.             result = kODTrue;
  273.     }
  274.     
  275.     return result;
  276. }
  277.  
  278. //------------------------------------------------------------------------------
  279. // PlatformFile::Lock
  280. //------------------------------------------------------------------------------
  281. void PlatformFile::Lock()
  282. {
  283.     THROW_IF_ERROR( FSpSetFLock(&fFileSpec) );
  284. }
  285.  
  286. //------------------------------------------------------------------------------
  287. // PlatformFile::Unlock
  288. //------------------------------------------------------------------------------
  289. void PlatformFile::Unlock()
  290. {
  291.     THROW_IF_ERROR( FSpRstFLock(&fFileSpec) );
  292. }
  293.  
  294.  
  295. //------------------------------------------------------------------------------
  296. // PlatformFile::IsStationery
  297. //------------------------------------------------------------------------------
  298. ODBoolean PlatformFile::IsStationery()
  299. {
  300.     FInfo fileInfo;
  301.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec,&fileInfo) );
  302.     return (((fileInfo.fdFlags)&kIsStationary)!=0);
  303. }
  304.  
  305. //------------------------------------------------------------------------------
  306. // PlatformFile::SetStationery
  307. //------------------------------------------------------------------------------
  308. void PlatformFile::SetStationery(ODBoolean isStationery)
  309. {
  310.     FInfo fileInfo;
  311.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec,&fileInfo) );
  312.     if (isStationery)
  313.         (fileInfo.fdFlags) |= kIsStationary;
  314.     else
  315.         (fileInfo.fdFlags) &= ~kIsStationary;
  316.     THROW_IF_ERROR( FSpSetFInfo(&fFileSpec,&fileInfo) );
  317.     BumpFolderModDate();
  318. }
  319.  
  320.  
  321. //------------------------------------------------------------------------------
  322. // PlatformFile::SetCustomIcon
  323. //------------------------------------------------------------------------------
  324. void PlatformFile::SetCustomIcon(ODBoolean hasCustomIcon)
  325. {
  326.     FInfo fileInfo;
  327.  
  328.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec, &fileInfo) );
  329.     if (hasCustomIcon)
  330.         (fileInfo.fdFlags) |= kHasCustomIcon;
  331.     else
  332.         (fileInfo.fdFlags) &= ~kHasCustomIcon;
  333.     THROW_IF_ERROR( FSpSetFInfo(&fFileSpec, &fileInfo) );
  334.     BumpFolderModDate();
  335. }
  336.  
  337. //------------------------------------------------------------------------------
  338. // PlatformFile::HasCustomIcon
  339. //------------------------------------------------------------------------------
  340. ODBoolean PlatformFile::HasCustomIcon()
  341. {
  342.     FInfo fileInfo;
  343.  
  344.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec, &fileInfo) );
  345.     return (fileInfo.fdFlags &= kHasCustomIcon ? kODTrue : kODFalse);
  346. }
  347.  
  348. //------------------------------------------------------------------------------
  349. // PlatformFile::IsDirectory
  350. //------------------------------------------------------------------------------
  351. ODBoolean PlatformFile::IsDirectory()
  352. {    
  353.     ODBoolean isDirectory = kODFalse;
  354.     
  355.     if( fFileID == kODNoFileID ) {
  356.         CInfoPBRec    pbBlock;
  357.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  358.         pbBlock.hFileInfo.ioFDirIndex = 0;
  359.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  360.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  361.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  362.         THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  363.         isDirectory = pbBlock.dirInfo.ioFlAttrib & 0x10 ? kODTrue : kODFalse;
  364.     }
  365.     return isDirectory;
  366. }
  367.  
  368. //------------------------------------------------------------------------------
  369. // PlatformFile::IsEqualTo
  370. //------------------------------------------------------------------------------
  371. ODBoolean PlatformFile::IsEqualTo(PlatformFile* file)
  372. {
  373.     return (fFileSpec.parID == file->fFileSpec.parID &&
  374.             fFileSpec.vRefNum == file->fFileSpec.vRefNum &&
  375.             EqualPascalStrings(fFileSpec.name, file->fFileSpec.name));
  376. }
  377.  
  378. //------------------------------------------------------------------------------
  379. // PlatformFile::GetFInfoFlags
  380. //------------------------------------------------------------------------------
  381. ODUShort    PlatformFile::GetFInfoFlags()
  382. {
  383.     FInfo fileInfo;
  384.  
  385.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec, &fileInfo) );
  386.     return fileInfo.fdFlags;
  387. }
  388.  
  389. //------------------------------------------------------------------------------
  390. // PlatformFile::Create
  391. //------------------------------------------------------------------------------
  392. void PlatformFile::Create(ODOSType creator, ODOSType fileType, ODScriptCode scriptCode)
  393. {    
  394.     
  395.     if (fDataRefNum == kODNoFileRefNum) {
  396.         THROW_IF_ERROR( FSpCreate(&fFileSpec, creator, fileType, scriptCode) );
  397.     }
  398.     fCreator = creator;
  399.     fFileType = fileType;
  400.     fScriptTag = scriptCode;
  401.     
  402.     this->GetFileID();
  403. }
  404.  
  405. //------------------------------------------------------------------------------
  406. // PlatformFile::CreateResFile
  407. //------------------------------------------------------------------------------
  408. void PlatformFile::CreateResFile()
  409. {
  410.     if (fResRefNum == kODNoFileRefNum)
  411.     {
  412.         FSpCreateResFile(&fFileSpec, fCreator, fFileType, fScriptTag);
  413.         THROW_IF_ERROR(ResError());
  414.     }
  415.     this->GetFileID();
  416. }
  417.  
  418. //------------------------------------------------------------------------------
  419. // PlatformFile::OpenResFile
  420. //------------------------------------------------------------------------------
  421. void PlatformFile::OpenResFile()
  422. {
  423.     ASSERT(fResOpenStack >= 0, kODErrAssertionFailed);
  424.     if (fResRefNum == kODNoFileRefNum)
  425.     {
  426.         ASSERT(fResOpenStack == 0, fResOpenStack);
  427.         fResRefNum = GetFirstLocalPath(PlatformFile::kODResourceFork);
  428.         if (fResRefNum != kODNoFileRefNum)
  429.         {
  430.             // Resource fork is already open
  431.             UseResFile(fResRefNum);
  432.             fNeedToClose = kODFalse;
  433.         }
  434.         else
  435.         {
  436.             // Resource fork is closed
  437.             fResRefNum = FSpOpenResFile(&fFileSpec, fPermission);
  438.             if (fResRefNum == -1 && fPermission != fsRdPerm)
  439.             {
  440.                 fResRefNum = kODNoFileRefNum;
  441.                 CreateResFile();
  442.                 fResRefNum = FSpOpenResFile(&fFileSpec, fPermission);
  443.             }
  444.             OSErr err = ResError();
  445.             if (err != eofErr)
  446.             {
  447.                 if (fResRefNum == -1)
  448.                     fResRefNum = kODNoFileRefNum;
  449.                 THROW_IF_ERROR(ResError());
  450.             }
  451.             if (fResRefNum == -1)
  452.             {
  453.                 fResRefNum = kODNoFileRefNum;
  454.                 THROW(resFNotFound);
  455.             }
  456.             fNeedToClose = kODTrue;
  457.         }
  458.     }
  459.     else
  460.         UseResFile(fResRefNum);
  461.     ++fResOpenStack;
  462. }
  463.  
  464. //------------------------------------------------------------------------------
  465. // PlatformFile::CloseResFile
  466. //------------------------------------------------------------------------------
  467. void PlatformFile::CloseResFile()
  468. {
  469.     ASSERT(fResOpenStack > 0, fResOpenStack);
  470.     if (--fResOpenStack == 0 && fNeedToClose)
  471.     {
  472.         ::CloseResFile(fResRefNum);
  473.         THROW_IF_ERROR(ResError());
  474.         fResRefNum = kODNoFileRefNum;
  475.     }
  476. }
  477.  
  478. //------------------------------------------------------------------------------
  479. // PlatformFile::GetFileID
  480. //------------------------------------------------------------------------------
  481. void PlatformFile::GetFileID()
  482. {
  483.     if( fFileID == kODNoFileID ) {
  484.         CInfoPBRec    pbBlock;
  485.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  486.         pbBlock.hFileInfo.ioFDirIndex = 0;
  487.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  488.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  489.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  490.         THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  491.         fFileID = pbBlock.hFileInfo.ioDirID;    /* for tracking the file later */
  492.     }
  493. }
  494.  
  495. //------------------------------------------------------------------------------
  496. // PlatformFile::UpdateSpecFromID
  497. //------------------------------------------------------------------------------
  498. void PlatformFile::UpdateSpecFromID()
  499. {
  500.     if (fFileID != kODNoFileID) {    /* make sure got the latest name in file spec */
  501.         HParamBlockRec hPB;
  502.         hPB.fidParam.ioCompletion = kODNULL;
  503.         hPB.fidParam.ioNamePtr = fFileSpec.name;
  504.         hPB.fidParam.ioVRefNum = fFileSpec.vRefNum;
  505.         hPB.fidParam.ioFileID = fFileID;
  506.         if (PBResolveFileIDRefSync(&hPB) == noErr)    /* ignore any error */
  507.             fFileSpec.parID = hPB.fidParam.ioSrcDirID;
  508.     }
  509. }
  510.  
  511.  
  512. //------------------------------------------------------------------------------
  513. // PlatformFile::Exists
  514. //------------------------------------------------------------------------------
  515. ODBoolean PlatformFile::Exists()
  516. {
  517.     const ODFileSpec &filespec = this->GetFileSpec();
  518.     FInfo ignore ;
  519.     OSErr err = FSpGetFInfo( &filespec, &ignore );
  520.     if ( err == noErr )
  521.         return kODTrue ;
  522.     else {
  523.         if ( err != fnfErr )
  524.             THROW( err );
  525.         return kODFalse ;
  526.     }
  527. }
  528.  
  529. //------------------------------------------------------------------------------
  530. // PlatformFile::Open
  531. //------------------------------------------------------------------------------
  532. void PlatformFile::Open()
  533. {    
  534.     if (fDataRefNum == kODNoFileRefNum) {
  535.         this->GetFileID();
  536.         THROW_IF_ERROR(FSpOpenDF(&fFileSpec, fPermission, &fDataRefNum));
  537.     }
  538.     else
  539.         THROW(kODErrFileOpened);
  540. }
  541.  
  542. //------------------------------------------------------------------------------
  543. // PlatformFile::Close
  544. //------------------------------------------------------------------------------
  545. void PlatformFile::Close()
  546. {    
  547.     if (fDataRefNum != kODNoFileRefNum) {
  548.         THROW_IF_ERROR(FSClose(fDataRefNum));
  549.         fDataRefNum = kODNoFileRefNum;
  550.     }
  551.     else
  552.         THROW(kODErrFileClosed);
  553. }
  554.  
  555. //------------------------------------------------------------------------------
  556. // PlatformFile::Delete
  557. //------------------------------------------------------------------------------
  558. void PlatformFile::Delete()
  559. {    
  560.     THROW_IF_ERROR(FSpDelete(&fFileSpec));
  561.     fFileID = kODNoFileID;
  562. }
  563.  
  564.  
  565. //------------------------------------------------------------------------------
  566. // PlatformFile::FlushVolume
  567. //------------------------------------------------------------------------------
  568. void PlatformFile::FlushVolume()
  569. {    
  570.     if (fDataRefNum != kODNoFileRefNum) {
  571.         ParamBlockRec    pb;
  572.     
  573.         pb.ioParam.ioCompletion = kODNULL;
  574.         pb.ioParam.ioRefNum = fDataRefNum;
  575.         (void) PBFlushFileSync(&pb);
  576.     }
  577.  
  578.     (void) FlushVol(kODNULL, fFileSpec.vRefNum);
  579. }
  580.  
  581. //------------------------------------------------------------------------------
  582. // PlatformFile::SetFilePos
  583. //------------------------------------------------------------------------------
  584. void PlatformFile::SetFilePos(ODSShort posMode, ODSLong posOff)
  585. {    
  586.     THROW_IF_ERROR(SetFPos(fDataRefNum, posMode, posOff));
  587. }
  588.  
  589. //------------------------------------------------------------------------------
  590. // PlatformFile::GetFilePos
  591. //------------------------------------------------------------------------------
  592. ODSLong PlatformFile::GetFilePos()
  593. {
  594.     ODSLong    posOff;
  595.     
  596.     THROW_IF_ERROR(GetFPos(fDataRefNum, &posOff));
  597.     return posOff;
  598. }
  599.  
  600. //------------------------------------------------------------------------------
  601. // PlatformFile::Read
  602. //------------------------------------------------------------------------------
  603. void PlatformFile::Read(void* buffer, ODSLong* count)
  604. {    
  605.     THROW_IF_ERROR(FSRead(fDataRefNum, count, buffer));
  606. }
  607.  
  608. //------------------------------------------------------------------------------
  609. // PlatformFile::Write
  610. //------------------------------------------------------------------------------
  611. void PlatformFile::Write(const void* buffer, ODSLong* count)
  612. {    
  613.     THROW_IF_ERROR(FSWrite(fDataRefNum, count, buffer));
  614. }
  615.  
  616. //------------------------------------------------------------------------------
  617. // PlatformFile::GetEndOfFile
  618. //------------------------------------------------------------------------------
  619. ODSLong PlatformFile::GetEndOfFile()
  620. {    
  621.     ODSLong    length;
  622.     
  623.     THROW_IF_ERROR(GetEOF(fDataRefNum, &length));
  624.     return length;
  625. }
  626.  
  627. //------------------------------------------------------------------------------
  628. // PlatformFile::SetEndOfFile
  629. //------------------------------------------------------------------------------
  630. void  PlatformFile::SetEndOfFile(ODSLong length)
  631. {    
  632.     THROW_IF_ERROR(SetEOF(fDataRefNum, length));
  633. }
  634.  
  635. //------------------------------------------------------------------------------
  636. // PlatformFile::GetName
  637. //------------------------------------------------------------------------------
  638. ODName* PlatformFile::GetName()
  639. {
  640.     this->UpdateSpecFromID();
  641.  
  642.     return CreateIText(fScriptTag, 0, fFileSpec.name);
  643. }
  644.  
  645. //------------------------------------------------------------------------------
  646. // PlatformFile::GetAsciiName
  647. //------------------------------------------------------------------------------
  648. void PlatformFile::GetAsciiName(char* asciiName, ODULong maxLength)
  649. {
  650.     this->UpdateSpecFromID();
  651.  
  652.     ODULong n = fFileSpec.name[0];
  653.     if( n > maxLength )
  654.         n = maxLength;
  655.     ODBlockMove(&(fFileSpec.name[1]), asciiName, n);
  656.     asciiName[n] = '\0';
  657. }
  658.  
  659. //------------------------------------------------------------------------------
  660. // PlatformFile::GetPlatformCreator
  661. //------------------------------------------------------------------------------
  662. ODOSType PlatformFile::GetPlatformCreator()
  663. {
  664.     if (fCreator == kBogusOSType) {
  665.         FInfo    fileInfo;
  666.         THROW_IF_ERROR(FSpGetFInfo(&fFileSpec, &fileInfo));
  667.         fCreator = fileInfo.fdCreator;
  668.         fFileType = fileInfo.fdType;
  669.     }
  670.     return fCreator;
  671. }    
  672.  
  673. //------------------------------------------------------------------------------
  674. // PlatformFile::GetPlatformType
  675. //------------------------------------------------------------------------------
  676. ODOSType PlatformFile::GetPlatformType()
  677. {
  678.     if (fFileType == kBogusOSType) {
  679.         FInfo    fileInfo;
  680.         THROW_IF_ERROR(FSpGetFInfo(&fFileSpec, &fileInfo));
  681.         fCreator = fileInfo.fdCreator;
  682.         fFileType = fileInfo.fdType;
  683.     }
  684.     return fFileType;
  685. }    
  686.  
  687. //------------------------------------------------------------------------------
  688. // PlatformFile::SetPlatformType
  689. //------------------------------------------------------------------------------
  690. void PlatformFile::SetPlatformType(ODOSType fileType)
  691. {
  692.     FInfo    fileInfo;
  693.     THROW_IF_ERROR(FSpGetFInfo(&fFileSpec, &fileInfo));
  694.     if( fileInfo.fdType != fileType ) {
  695.         fileInfo.fdType = fileType;
  696.         THROW_IF_ERROR(FSpSetFInfo(&fFileSpec, &fileInfo));
  697.         fFileType = fileType;
  698.         this->BumpFolderModDate();
  699.     }
  700. }    
  701.  
  702.  
  703. //------------------------------------------------------------------------------
  704. // PlatformFile::GetContainerType
  705. //------------------------------------------------------------------------------
  706.  
  707. ODContainerType PlatformFile::GetContainerType()
  708. {
  709.     if (fContainerType == kODNULL)
  710.         fContainerType =
  711.             (ODContainerType)
  712.             (this->ReadResourcePtr(kFileContainerType, kFileContainerTypeResID, kODNULL));
  713.  
  714.     return fContainerType;
  715. }
  716.  
  717. //------------------------------------------------------------------------------
  718. // PlatformFile::SetContainerType
  719. //------------------------------------------------------------------------------
  720.  
  721. void PlatformFile::SetContainerType(ODContainerType containerType)
  722. {
  723.     ODDisposePtr(fContainerType);
  724.     fContainerType = containerType;
  725.  
  726.     this->WriteResourcePtr(kFileContainerType, kFileContainerTypeResID, 
  727.                         (ODPtr)containerType, strlen(containerType)+1);
  728. }
  729.  
  730.  
  731. //------------------------------------------------------------------------------
  732. // CWithActiveResources class
  733. //------------------------------------------------------------------------------
  734.  
  735. // [HLX] because ~Destructo is not defined
  736. Destructo::~Destructo()
  737. {
  738. }
  739. // [HLX] because ~Destructo is not defined
  740.  
  741. class CWithActiveResources :Destructo {
  742.     public:
  743.     CWithActiveResources( PlatformFile* );
  744.    ~CWithActiveResources( );
  745.     private:
  746.     PlatformFile    *fFile;
  747.     ODFileRefNum    fCurResFile;
  748.     ODBoolean        fSuccessfullyOpened;
  749. };
  750.  
  751. CWithActiveResources::CWithActiveResources( PlatformFile *pf )
  752. {
  753.     fSuccessfullyOpened = kODFalse;
  754.     fFile = pf;
  755.     fCurResFile = CurResFile();
  756.     fFile->OpenResFile();
  757.     fSuccessfullyOpened = kODTrue;
  758. }
  759.  
  760. CWithActiveResources::~CWithActiveResources( )
  761. {
  762.     if (fSuccessfullyOpened)
  763.         fFile->CloseResFile();
  764.     UseResFile(fCurResFile);
  765. }
  766.         
  767.  
  768. //------------------------------------------------------------------------------
  769. // PlatformFile::ReadResourcePtr
  770. //------------------------------------------------------------------------------
  771. ODPtr PlatformFile::ReadResourcePtr(ODPlatformType resType, ODSShort resID, ODULong* size)
  772. {
  773.     ODPtr resPtr = kODNULL;     ODVolatile(resPtr);    // Method Specific
  774.     
  775.     TRY
  776.         CWithActiveResources w(this); // this throws if no resfile
  777.         
  778.         Handle resHandle = Get1Resource(resType, resID);
  779.         if (resHandle != kODNULL)
  780.         {
  781.             HNoPurge(resHandle);
  782.             ODULong hsize = GetHandleSize(resHandle);
  783.             if (size != kODNULL)
  784.                 *size = hsize;
  785.             resPtr = ODNewPtrClear(hsize,0);
  786.             ODBlockMove(*resHandle,resPtr, hsize);
  787.             ReleaseResource(resHandle);
  788.         } else if( ResError() != resNotFound )
  789.             THROW_IF_ERROR(ResError());
  790.  
  791.     CATCH_ALL
  792.     ENDTRY
  793.     
  794.     return resPtr;  // Method Specific
  795. }
  796.  
  797. //------------------------------------------------------------------------------
  798. // PlatformFile::WriteResourcePtr
  799. //------------------------------------------------------------------------------
  800. void PlatformFile::WriteResourcePtr(ODPlatformType resType, ODSShort resID, 
  801.                                     const void *resPtr, ODULong size)
  802. {
  803.     ASSERT(resPtr!=kODNULL,kODErrIllegalNullInput);
  804.     
  805.     SetPermission(fsRdWrPerm);
  806.     CWithActiveResources w(this);
  807.     
  808.     Handle resHandle = Get1Resource(resType,resID);
  809.     if( ResError() != resNotFound )
  810.         THROW_IF_ERROR(ResError());
  811.         
  812.     ODBoolean needsAdding = (resHandle == kODNULL);
  813.     if (needsAdding)
  814.         resHandle = ODNewHandle(size);
  815.     else {
  816.         HNoPurge(resHandle);
  817.         ODSetHandleSize(resHandle, size);
  818.     }
  819.     
  820.     ODBlockMove(resPtr,*resHandle, size);
  821.     
  822.     if (needsAdding)
  823.         AddResource(resHandle,resType,resID,"\p");
  824.     else
  825.         ChangedResource(resHandle);
  826.     THROW_IF_ERROR(ResError());
  827. }
  828.  
  829.  
  830. //------------------------------------------------------------------------------
  831. // PlatformFile::DeleteResource
  832. //------------------------------------------------------------------------------
  833. void PlatformFile::DeleteResource(ODPlatformType resType, ODSShort resID)
  834. {
  835.     SetPermission(fsRdWrPerm);
  836.     CWithActiveResources w(this);
  837.     
  838.     Handle resHandle = Get1Resource(resType, resID);
  839.     OSErr err= ResError();
  840.     if( resHandle ) {
  841.         RemoveResource(resHandle);
  842.         err= ResError();
  843.         if( !err )
  844.             DisposeHandle(resHandle);    // After RemoveResource it's not a rsrc
  845.     } else {
  846.         if( err == resNotFound )
  847.             err = noErr;
  848.     }
  849.     THROW_IF_ERROR(err);
  850. }
  851.  
  852. //------------------------------------------------------------------------------
  853. // PlatformFile::GetAllocationBlockSize
  854. //------------------------------------------------------------------------------
  855. ODULong PlatformFile::GetAllocationBlockSize()
  856. {
  857.     HParamBlockRec pb;
  858.     
  859.     pb.volumeParam.ioCompletion = kODNULL;
  860.     pb.volumeParam.ioNamePtr = kODNULL;
  861.     pb.volumeParam.ioVRefNum = fFileSpec.vRefNum;
  862.     pb.volumeParam.ioVolIndex = 0;
  863.  
  864.     THROW_IF_ERROR(PBHGetVInfoSync(&pb));
  865.  
  866.     return pb.volumeParam.ioVAlBlkSiz;
  867. }
  868.  
  869. //------------------------------------------------------------------------------
  870. // PlatformFile::CopyFrom
  871. //------------------------------------------------------------------------------
  872. void PlatformFile::CopyFrom( PlatformFile* src )
  873. {
  874.     ODBoolean srcIsOpen = (src->GetFileRefNum() != kODNoFileRefNum);
  875.     if ( !srcIsOpen )
  876.         src->Open();
  877.     this->SetPermission( fsRdWrPerm );        // currently this is the default value
  878.     if (!this->Exists())
  879.         this->Create(src->GetPlatformCreator(), src->GetPlatformType(), 0 /*$$$$$ scriptcode?*/);
  880.  
  881.     this->Open();
  882.             
  883.     src->SetFilePos( fsFromStart, 0 );
  884.     this->SetFilePos( fsFromStart, 0 );
  885.     
  886.     ODSLong bytesLeft = src->GetEndOfFile();
  887.  
  888.     TempODHandle hbuffer = kODNULL;
  889.     ODSLong bufferSize = kMaxCopyBufferSize;
  890.     if( bufferSize > bytesLeft )
  891.         bufferSize = bytesLeft;
  892.     for( ; bufferSize>=kMinCopyBufferSize; bufferSize /= 2 ) {
  893.         OSErr err;
  894.         hbuffer= TempNewHandle(bufferSize,&err);
  895.         if( hbuffer ) break;
  896.     }
  897.     WASSERT(bufferSize > 0);
  898.     THROW_IF_NULL(hbuffer);
  899.     void *buffer = *hbuffer;
  900.     
  901.     ODSLong count;
  902.  
  903.     while( bytesLeft > 0 )
  904.     {
  905.         count = bytesLeft < bufferSize? bytesLeft: bufferSize ;
  906.         WASSERT(count > 0);
  907.         src->Read( buffer, &count );
  908.         this->Write( buffer, &count );
  909.         bytesLeft -= count ;
  910.     }
  911.     
  912.     if ( !srcIsOpen )
  913.         src->Close();
  914.     this->Close();
  915. }
  916.  
  917. //------------------------------------------------------------------------------
  918. // PlatformFile::MoveRename
  919. //------------------------------------------------------------------------------
  920. void PlatformFile::MoveRename( ODFileSpec* newSpec, ODBoolean isDuplicate )
  921. {
  922.     // This will fail if a file with the old name already exists in the
  923.     // target directory. MoreFiles (DTS) has a more robust version of this.
  924.     
  925.     ASSERT(newSpec->vRefNum == fFileSpec.vRefNum, kODErrAssertionFailed);
  926.  
  927.     if ( isDuplicate )
  928.     {
  929.         THROW_IF_ERROR( FSpDelete( newSpec ) ); 
  930.     }
  931.  
  932.     this->Move( newSpec->parID );
  933.     this->Rename( newSpec->name );
  934. }    // MoveRename()
  935.  
  936.  
  937. //------------------------------------------------------------------------------
  938. // PlatformFile::Move
  939. //------------------------------------------------------------------------------
  940.  
  941. void PlatformFile::Move( ODSLong targetParID )
  942. {
  943.     CMovePBRec paramBlock ;
  944.     memset( ¶mBlock, 0, sizeof(paramBlock) );
  945.     
  946.     paramBlock.ioNamePtr = fFileSpec.name ;
  947.     paramBlock.ioVRefNum = fFileSpec.vRefNum ;
  948.     paramBlock.ioNewDirID = targetParID ;
  949.     paramBlock.ioDirID = fFileSpec.parID ;
  950.     
  951.     (void) HDelete(fFileSpec.vRefNum,targetParID,fFileSpec.name);     // ignore error (may not exist)
  952.     OSErr err = PBCatMoveSync( ¶mBlock );
  953.     THROW_IF_ERROR( err );
  954.  
  955.     fFileSpec.parID = targetParID ;
  956. }
  957.  
  958. //------------------------------------------------------------------------------
  959. // PlatformFile::UniquifyName
  960. // Given in this a platformfile (whose filespec only is used) that may conflict
  961. // with an existing file, deal with this conflict in one of two ways depending
  962. // on the value of action.  The two values are:
  963. // 1. kSpecifyNewNameOnly: just change the name field of the filespec so that the
  964. // platform file represents a file that would be unique if created
  965. // 2. kRenameInPlace: this file already exists, but we want it to have a different
  966. // name so we can reuse this one.  Find that name, and rename the actual file.
  967. // 
  968. // Two string templates are expected, and the caller can either pass in their
  969. // resource IDs or StringHandles to the strings themselves, signifying the latter
  970. // with a resource ID of kODNoResourceID.  The first of these strings is used
  971. // the first time through the renaming loop (which typically sticks something
  972. // like " copy" on the end of the file name, and the second is used thereafter
  973. // (when increasingly large numbers are put into the string in an attempt to
  974. // make it unique.
  975. //------------------------------------------------------------------------------
  976.  
  977. void PlatformFile::UniquifyName( ODSShort uniquifyingStringID,
  978.             StringHandle uniquifyingString, 
  979.             ODSShort uniquifyingNumberID,
  980.             StringHandle uniquifyingNumberString, 
  981.             short copyCount,
  982.             PFUniquifyAction action, 
  983.             ODBoolean forceNewName)
  984. {
  985.     if ((forceNewName!=kODTryCurrentName) || this->Exists() )
  986.     {
  987.         PlatformFile* possibleOther = new PlatformFile;
  988.         TempPlatformFile t = possibleOther;        // save so will get deconstructed
  989. //        possibleOther->SpecifyFromFile( this );
  990.     
  991.         // Get the strings to be used in substitution if they weren't passed in.
  992.         // Assign them to tempobjs so we don't have to dispose later.  Don't assign
  993.         // if they're passed in (of course....)
  994.         TempODHandle registerNoNumHandleIfLocal = kODNULL;
  995.         TempODHandle registerNumHandleIfLocal = kODNULL;
  996.         CUsingLibraryResources r;
  997.         if ( uniquifyingStringID != kODNoResourceID )
  998.         {
  999.             WASSERT( !uniquifyingString );
  1000.             uniquifyingString = GetString( uniquifyingStringID );
  1001.             DetachResource( (Handle)uniquifyingString );
  1002.             registerNoNumHandleIfLocal = (Handle)uniquifyingString;
  1003.             WASSERT( uniquifyingString );
  1004.         }
  1005.         if ( uniquifyingNumberID != kODNoResourceID )
  1006.         {
  1007.             WASSERT(!uniquifyingNumberString);
  1008.             uniquifyingNumberString = GetString( uniquifyingNumberID );
  1009.             DetachResource( (Handle)uniquifyingNumberString );
  1010.             registerNumHandleIfLocal = (Handle)uniquifyingNumberString;
  1011.         }
  1012.         WASSERT(uniquifyingNumberString);
  1013.     
  1014.         ODFileSpec localCopy = this->GetFileSpec();
  1015.         // save the name (as we'll be munging localCopy)
  1016.         Str63 originalName;
  1017.         ODBlockMove( localCopy.name, originalName, localCopy.name[0]+1 );
  1018.     
  1019.         TempODHandle baseText = ODNewHandle(kMaxFileNameSize+1);
  1020.         THROW_IF_NULL(baseText);
  1021.         TempODHandle substitutionText = ODNewHandle(kMaxFileNameSize+1);
  1022.         THROW_IF_NULL(substitutionText);
  1023.     
  1024.         ODBoolean nameNeedsNumber = (uniquifyingString == kODNULL);
  1025.             // if there is no uniquifyingString, we immediately need to start using
  1026.             // the uniquifyingNumberString, or in other words nameNeedsNumber==true.
  1027.             
  1028.         for ( ; ; nameNeedsNumber = kODTrue)
  1029.         {
  1030.             // nameNeedsNumber = copyCount > 1;
  1031.             StringHandle templateToUse = nameNeedsNumber ?
  1032.                     uniquifyingNumberString : uniquifyingString;
  1033.     
  1034.             short thisTemplateLen = **templateToUse;
  1035.             // <eeh> NOTE that this forces callers to have two ^number tuples in the
  1036.             // second template.
  1037.             thisTemplateLen -= nameNeedsNumber? 4 : 2;
  1038.     
  1039.             short numberLen;
  1040.             Str32 numberString;
  1041.             if ( nameNeedsNumber )
  1042.             {
  1043.                 NumToString( copyCount, numberString );
  1044.                 numberLen = numberString[0];
  1045.             }
  1046.             else
  1047.                 numberLen = 0;
  1048.     
  1049.             // truncate the name if after appending it will be too long
  1050.             Str63 localName;
  1051.             ODBlockMove( originalName, localName, originalName[0] + 1 );
  1052.             short postAppendLen = localName[0] + thisTemplateLen + numberLen;
  1053.             if ( postAppendLen > kODMaxFileNameSize )
  1054.                 ClipStringToBytes( localName,
  1055.                         kODMaxFileNameSize - thisTemplateLen - numberLen, fScriptTag );
  1056.     
  1057.             // copy the template into the base handle, then pass in the possible file
  1058.             // name
  1059.             short len;
  1060.             SetHandleSize( baseText, len = **templateToUse );
  1061.             ODBlockMove( (*templateToUse)+1, *baseText, len );
  1062.             SetHandleSize( substitutionText, len = localName[0] );
  1063.             ODBlockMove( &localName[1], *substitutionText, len );
  1064.             short err = ReplaceText( baseText, substitutionText, "\p^0" );
  1065.             WASSERT( err >= 0 );
  1066.             
  1067.             if ( nameNeedsNumber )        // do same for number
  1068.             {
  1069.                 SetHandleSize( substitutionText, len = numberString[0] );
  1070.                 ODBlockMove( &numberString[1], *substitutionText, len );
  1071.                 err = ReplaceText( baseText, substitutionText, "\p^1" );
  1072.                 WASSERT( err >= 0 );
  1073.             }
  1074.     
  1075.             ODBlockMove( *baseText, &localCopy.name[1], len = GetHandleSize(baseText) );
  1076.             localCopy.name[0] = len;
  1077.     
  1078.             possibleOther->Specify( &localCopy );
  1079.             if ( !possibleOther->Exists() )
  1080.             {
  1081.                 WASSERT( localCopy.name[0] <= kODMaxFileNameSize );
  1082.                 if ( action == kSpecifyNewNameOnly )
  1083.                 {
  1084.                     // set up this so that when created it will represent a unique file
  1085.                     PascalToCString( localCopy.name );
  1086.                     this->SetAsciiName( (char*)localCopy.name );
  1087.                 }
  1088.                 else if ( action == kRenameInPlace )
  1089.                 {
  1090.                     // put the original file spec back in the target, then call
  1091.                     // Rename passing in the new name
  1092.                     WASSERT(this->Exists());
  1093.                     this->Rename( localCopy.name );
  1094.                 }
  1095.                 else
  1096.                     WARN( "unknown PFUniquifyAction" );
  1097.                 break;
  1098.             }
  1099.             if (nameNeedsNumber)
  1100.                 ++copyCount;        
  1101.                 // Gets executed after 2nd time through loop if there was a valid
  1102.                 // uniquifyString.  
  1103.                 // Otherwise gets executed after 1st time through loop.
  1104.         }
  1105.     }
  1106. }    // UniquifyName
  1107.  
  1108. //------------------------------------------------------------------------------
  1109. // PlatformFile::MoveToTrash
  1110. //------------------------------------------------------------------------------
  1111.  
  1112. void PlatformFile::MoveToTrash()
  1113. {
  1114.     ODSLong parID = fFileSpec.parID;
  1115.     ODSLong            trashDirID;
  1116.     THROW_IF_ERROR(FindFolder(fFileSpec.vRefNum, kTrashFolderType, kCreateFolder,
  1117.                             &(fFileSpec.vRefNum), &trashDirID));
  1118.                             
  1119.     // Move deletes any file that may conflict with the file once moved, but
  1120.     // in this case that isn't what we want.  So check if such a file exists,
  1121.     // and if so rename the conflicting file first (following the Finder's
  1122.     // model.)
  1123.     ODFileSpec possibleOtherFS = this->GetFileSpec();
  1124.     possibleOtherFS.parID = trashDirID;
  1125.     PlatformFile target;        // represents a file that *may* be in the trash
  1126.     target.Specify( &possibleOtherFS );
  1127.     
  1128. #if 1
  1129. //    if ( target.Exists() )
  1130.     {
  1131.         CUsingLibraryResources r;
  1132.         target.UniquifyName( kCopyDefaultNameNoNumStrID, kODNULL,
  1133.                 kCopyDefaultNameWithNumStrID, kODNULL, 2, kRenameInPlace,
  1134.                 kODTryCurrentName ) ;
  1135.     }
  1136. #else
  1137.     Str32 uniqueName;
  1138.     if ( MakeUniqueFileName( &target, kCopyDefaultNameNoNumStrID,
  1139.             kCopyDefaultNameWithNumStrID, 31, uniqueName ) )
  1140.         target.Rename( uniqueName );
  1141. #endif
  1142.     this->Move(trashDirID);
  1143.  
  1144.     CInfoPBRec pbRec;
  1145.     pbRec.hFileInfo.ioCompletion = NULL;
  1146.     pbRec.hFileInfo.ioNamePtr = fFileSpec.name;
  1147.     pbRec.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1148.     pbRec.hFileInfo.ioFDirIndex = 0;
  1149.     pbRec.hFileInfo.ioDirID = fFileSpec.parID;
  1150.     
  1151.     
  1152.     if ( PBGetCatInfoSync( &pbRec ) == noErr )
  1153.     {
  1154.         // <eeh> stuffing this field *may* not work under Copland
  1155.         pbRec.hFileInfo.ioFlXFndrInfo.fdPutAway = parID;
  1156.         // this was changed by PBGetCatInfoSync...
  1157.         pbRec.hFileInfo.ioDirID = fFileSpec.parID;
  1158.         (void)PBSetCatInfoSync( &pbRec );    // ignore the error
  1159.     }
  1160. }
  1161.  
  1162. //------------------------------------------------------------------------------
  1163. // PlatformFile::Rename
  1164. //        This routine will not yet delete a file that will prevent the
  1165. //            renaming (as Move() does above.)
  1166. //------------------------------------------------------------------------------
  1167. void PlatformFile::Rename( Str63 newName )
  1168. {
  1169.     this->UpdateSpecFromID();
  1170.     
  1171.     THROW_IF_ERROR( FSpRename( &fFileSpec, newName ) );
  1172.      CopyPascalString(fFileSpec.name, newName);
  1173.     BumpFolderModDate();
  1174. }
  1175.  
  1176.  
  1177. //------------------------------------------------------------------------------
  1178. // PlatformFile::GetFileModDate
  1179. //        This routine will set the file modification date to the input parameter
  1180. //------------------------------------------------------------------------------
  1181. ODTime PlatformFile::GetFileModDate()
  1182. {
  1183.     this->UpdateSpecFromID();
  1184.     
  1185.     CInfoPBRec    pbBlock;
  1186.     pbBlock.hFileInfo.ioCompletion = kODNULL;
  1187.     pbBlock.hFileInfo.ioFDirIndex = 0;
  1188.     pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1189.     pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1190.     pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1191.     THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  1192.     return pbBlock.hFileInfo.ioFlMdDat;
  1193. }
  1194.  
  1195.  
  1196. //------------------------------------------------------------------------------
  1197. // PlatformFile::SetFileModDate
  1198. //        This routine will set the file modification date to the input parameter
  1199. //------------------------------------------------------------------------------
  1200. void PlatformFile::SetFileModDate(ODTime date)
  1201. {
  1202.     this->UpdateSpecFromID();
  1203.     
  1204.     if (!this->IsLocked()) {
  1205.         CInfoPBRec    pbBlock;
  1206.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  1207.         pbBlock.hFileInfo.ioFDirIndex = 0;
  1208.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1209.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1210.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1211.         if (PBGetCatInfoSync(&pbBlock) == noErr) {
  1212.             pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1213.             pbBlock.hFileInfo.ioFlMdDat = date;
  1214.             (void) PBSetCatInfoSync(&pbBlock); /* who cares if it fails */
  1215.         }
  1216.     }
  1217. }
  1218.  
  1219. //------------------------------------------------------------------------------
  1220. // PlatformFile::SetFileCreationDate
  1221. //        This routine will set the file creation date to the input parameter
  1222. //------------------------------------------------------------------------------
  1223. void PlatformFile::SetFileCreationDate(ODTime date)
  1224. {
  1225.     this->UpdateSpecFromID();
  1226.  
  1227.     CInfoPBRec    pbBlock;
  1228.  
  1229.     if (!this->IsLocked()) {
  1230.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  1231.         pbBlock.hFileInfo.ioFDirIndex = 0;
  1232.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1233.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1234.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1235.         if (PBGetCatInfoSync(&pbBlock) == noErr) {
  1236.             pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1237.             pbBlock.hFileInfo.ioFlCrDat = date;
  1238.             (void) PBSetCatInfoSync(&pbBlock); /* who cares if it fails */
  1239.         }
  1240.     }
  1241. }
  1242.                 
  1243. //------------------------------------------------------------------------------
  1244. // PlatformFile::GetFileCreationDate
  1245. //        This routine will get the file creation date and return it.
  1246. //------------------------------------------------------------------------------
  1247. ODTime PlatformFile::GetFileCreationDate()
  1248. {
  1249.     this->UpdateSpecFromID();
  1250.     
  1251.     CInfoPBRec    pbBlock;
  1252.     pbBlock.hFileInfo.ioCompletion = kODNULL;
  1253.     pbBlock.hFileInfo.ioFDirIndex = 0;
  1254.     pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1255.     pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1256.     pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1257.     THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  1258.     return pbBlock.hFileInfo.ioFlCrDat;
  1259. }
  1260.             
  1261. //------------------------------------------------------------------------------
  1262. // PlatformFile::BumpFolderModDate
  1263. //        This routine will set the file modification date of the parent folder
  1264. //        to the current time so as to cause the Finder to refresh the folder if
  1265. //        it is open.  It only has WARNs if it errors.
  1266. //------------------------------------------------------------------------------
  1267. void PlatformFile::BumpFolderModDate()
  1268. {
  1269.     CInfoPBRec    theParamBlock;
  1270.  
  1271.     memset (&theParamBlock, 0, sizeof(theParamBlock));
  1272.     // ioNamePtr = 0
  1273.     theParamBlock.dirInfo.ioFDirIndex = -1;
  1274.     theParamBlock.dirInfo.ioVRefNum = fFileSpec.vRefNum;
  1275.     theParamBlock.dirInfo.ioDrDirID = fFileSpec.parID;
  1276.     OSErr err = PBGetCatInfoSync(&theParamBlock);
  1277.     if( err )
  1278.         WARN("Couldn't get dir mod date, err %hd",err);
  1279.     else
  1280.     {
  1281.         ODULong newTime;
  1282.  
  1283.         GetDateTime(&newTime);
  1284.         // set to the future if it is now
  1285.         if (theParamBlock.dirInfo.ioDrMdDat >= newTime)
  1286.             ++newTime;
  1287.         theParamBlock.dirInfo.ioDrMdDat = newTime;
  1288.         err = PBSetCatInfoSync(&theParamBlock);
  1289.         if( err )
  1290.             WARN("Couldn't bump dir mod date, err %hd",err);
  1291.     }
  1292. }
  1293.                 
  1294. //------------------------------------------------------------------------------
  1295. // PlatformFile::GetFirstLocalPath
  1296. //------------------------------------------------------------------------------
  1297.  
  1298. ODFileRefNum PlatformFile::GetFirstLocalPath( ODForkType fork )
  1299. {
  1300.     ODFileSpec* spec = &fFileSpec;
  1301.     
  1302.     OSErr        result;
  1303.     FCBPBRec    pb;
  1304.     short        index;
  1305.     Str31        tempName;
  1306.     
  1307.     /* Get FCB name in tempName */
  1308.     pb.ioNamePtr = tempName;
  1309.     
  1310.     /* Index through the open paths on the volume specified by fFileSpec.vRefNum */
  1311.     pb.ioVRefNum = fFileSpec.vRefNum;
  1312.     index = 1;
  1313.     do
  1314.     {
  1315.         pb.ioRefNum = 0;
  1316.         pb.ioFCBIndx = index;
  1317.         result = PBGetFCBInfoSync(&pb);
  1318.         if ( result == noErr )
  1319.         {
  1320.             /*
  1321.             **    See if parent directory ID matches and
  1322.             **    file name matches and
  1323.             **    the file fork (resource or data) matches
  1324.             */
  1325.             if ( (pb.ioFCBParID == fFileSpec.parID) &&
  1326.                  EqualString(fFileSpec.name, tempName, false, true) &&
  1327.                  ((fork == kODResourceFork) == ((pb.ioFCBFlags & (1 << 9)) != 0)) )
  1328.             {
  1329.                 return pb.ioRefNum;            // Found it!
  1330.             }
  1331.             ++index;    /* next FCB index */
  1332.         }
  1333.     } while ( result == noErr );
  1334.     
  1335.     return kODNoFileRefNum;
  1336. }
  1337.  
  1338.  
  1339. //------------------------------------------------------------------------------
  1340. // PlatformFile::GetLocalPaths
  1341. //------------------------------------------------------------------------------
  1342.  
  1343. ODError        PlatformFile::GetLocalPaths(
  1344.                               ODForkType fork,
  1345.                               ODULong *refNumCount,
  1346.                               ODFileRefNumPtr *refNums)
  1347. {
  1348.     const ODULong kMaxFCBs = 348;    /* The maximum number of local access paths under System 7 */
  1349.     
  1350.     OSErr        result;
  1351.     FCBPBRec    pb;
  1352.     short        index;
  1353.     Str31        tempName;
  1354.     ODFileRefNumPtr    tempRefNums;
  1355.     
  1356.     /* initialize returned values */
  1357.     *refNumCount = 0;
  1358.     *refNums = NULL;
  1359.     
  1360.     /* Allocate temp storage for refNum matches */
  1361.     tempRefNums = (ODFileRefNumPtr)ODNewPtr(kMaxFCBs * sizeof(short));
  1362.     
  1363.     if ( tempRefNums != NULL )
  1364.     {
  1365.         /* Get FCB name in tempName */
  1366.         pb.ioNamePtr = tempName;
  1367.         
  1368.         /* Index through the open paths on the volume specified by fFileSpec.vRefNum */
  1369.         pb.ioVRefNum = fFileSpec.vRefNum;
  1370.         index = 1;
  1371.         do
  1372.         {
  1373.             pb.ioRefNum = 0;
  1374.             pb.ioFCBIndx = index;
  1375.             result = PBGetFCBInfoSync(&pb);
  1376.             if ( result == noErr )
  1377.             {
  1378.                 /*
  1379.                 **    See if parent directory ID matches and
  1380.                 **    file name matches and
  1381.                 **    the file fork (resource or data) matches
  1382.                 */
  1383.                 if ( (pb.ioFCBParID == fFileSpec.parID) &&
  1384.                      EqualString(fFileSpec.name, tempName, false, true) &&
  1385.                      ((fork == kODResourceFork) == ((pb.ioFCBFlags & (1 << 9)) != 0)) )
  1386.                 {
  1387.                     /* It's a match - add it to the array of matches */
  1388.                     tempRefNums[*refNumCount] = pb.ioRefNum;
  1389.                     ++(*refNumCount);
  1390.                 }
  1391.                 ++index;    /* next FCB index */
  1392.             }
  1393.         } while ( result == noErr );
  1394.         
  1395.         /* These errors are OK - they mean we hit the end of the FCB list */
  1396.         if ( (result == rfNumErr) || (result == fnOpnErr) )
  1397.         {
  1398.             result = noErr;
  1399.         }
  1400.         
  1401.         if ( (result == noErr) && (*refNumCount != 0) )
  1402.         {
  1403.             // Note: the below two lines were a gratuitous change from the tested code
  1404.             // given to me by Jim Luther.  Therefore I have commented them out and returned
  1405.             // the original code. -Tantek
  1406.             //*refNums = (ODFileRefNumPtr) ODReallocate( tempRefNums, *refNumCount * sizeof(short) );
  1407.             //*tempRefNums = kODNULL;
  1408.             /* Allocate memory to return refNum matches in */
  1409.             *refNums = (ODFileRefNumPtr)ODNewPtr(*refNumCount * sizeof(short));
  1410.             if ( *refNums != NULL )
  1411.             {
  1412.                 /* Move refNums from tempRefNums to *refNums */
  1413.                 ODBlockMove((Ptr)tempRefNums, (Ptr)*refNums, (*refNumCount * sizeof(short)));
  1414.             }
  1415.             else
  1416.             {
  1417.                 /* Couldn't allocate memory for refNum array */
  1418.                 result = memFullErr;
  1419.             }
  1420.  
  1421.         }
  1422.         
  1423.         /* Free up tempRefNums storage */ 
  1424.         ODDisposePtr((Ptr)tempRefNums);
  1425.     }
  1426.     else
  1427.     {
  1428.         /* Couldn't allocate temp memory */
  1429.         result = memFullErr;
  1430.     }
  1431.     
  1432.     return ( result );
  1433. }
  1434.  
  1435. //------------------------------------------------------------------------------
  1436. // PlatformFile::GetComments
  1437. //
  1438. //    If a pointer is passed in, the text is placed there and a pointer to it is
  1439. //    returned.  If the comments pointer is null, then a new pointer is allocated
  1440. //    and returned.
  1441. //------------------------------------------------------------------------------
  1442.  
  1443. enum {
  1444.     uppPBDTInfo = kRegisterBased
  1445.          | RESULT_SIZE(sizeof(OSErr))
  1446.          | REGISTER_RESULT_LOCATION(kRegisterD0)
  1447.          
  1448.          | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(kTwoByteCode))    // trap word
  1449.          | REGISTER_ROUTINE_PARAMETER(2, kRegisterD0, SIZE_CODE(kTwoByteCode))    // selector
  1450.          
  1451.          | REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(DTPBRec*)))
  1452.          | REGISTER_ROUTINE_PARAMETER(4, kRegisterA3, SIZE_CODE(sizeof(void*)))
  1453. };
  1454.  
  1455. #if GENERATING68K && GENERATINGCFM
  1456. OSErr PBDTGetCommentSyncGlue(DTPBRec *pb);
  1457. OSErr PBDTGetCommentSyncGlue(DTPBRec *pb)
  1458. {
  1459.     void* hfsdispatch = GetOSTrapAddress(0xA260);
  1460.     return CallOSTrapUniversalProc((UniversalProcPtr) hfsdispatch,
  1461.                                     uppPBDTInfo,
  1462.                                     (short) 0xA260,    // trap word
  1463.                                     (short) 0x002A,    // selector
  1464.                                     pb,                // a1, the param block ptr
  1465.                                     pb                // a3 should be ignored
  1466.                                   );
  1467. }
  1468. #endif
  1469.  
  1470. #if GENERATING68K && GENERATINGCFM
  1471. OSErr PBDTSetCommentSyncGlue(DTPBRec *pb);
  1472. OSErr PBDTSetCommentSyncGlue(DTPBRec *pb)
  1473. {
  1474.     void* hfsdispatch = GetOSTrapAddress(0xA260);
  1475.     return CallOSTrapUniversalProc((UniversalProcPtr) hfsdispatch,
  1476.                                     uppPBDTInfo,
  1477.                                     (short) 0xA260,    // trap word
  1478.                                     (short) 0x0028,    // selector
  1479.                                     pb,                // a1, the param block ptr
  1480.                                     pb                // a3 should be ignored
  1481.                                   );
  1482. }
  1483. #endif
  1484.  
  1485. ODIText*    PlatformFile::GetComments(ODIText* comments)
  1486. {
  1487.     DTPBRec            pb;    
  1488.     memset( &pb, 0, sizeof(pb) );
  1489.     
  1490.     pb.ioVRefNum = fFileSpec.vRefNum;
  1491.     OSErr err = PBDTGetPath(&pb);
  1492.     if (err == noErr)
  1493.     {
  1494.         pb.ioNamePtr = fFileSpec.name;
  1495.         pb.ioDirID = fFileSpec.parID;
  1496.         char buffer[256];
  1497.         pb.ioDTBuffer = buffer;
  1498.  
  1499.         // avoid the crash on 68K if the PlatformFile is remote
  1500. #if GENERATING68K && GENERATINGCFM
  1501.         err = PBDTGetCommentSyncGlue(&pb);
  1502. #else
  1503.         err = PBDTGetCommentSync(&pb);
  1504. #endif
  1505.         if (err == noErr) {
  1506.             buffer[pb.ioDTActCount] = 0; // make it a c string
  1507.             if (comments == kODNULL)
  1508.             {
  1509.                 ODScriptCode script = FontToScript( GetSysFont() );
  1510.                 comments = CreateITextCString(script, 
  1511.                         GetScriptVariable( script, smScriptLang ), buffer);
  1512.             }
  1513.             else
  1514.                 SetITextCString(comments, buffer);
  1515.         }
  1516.     }
  1517.     
  1518.     return comments;
  1519. }
  1520.  
  1521. //------------------------------------------------------------------------------
  1522. // PlatformFile::SetComments
  1523. //------------------------------------------------------------------------------
  1524.  
  1525. void
  1526. PlatformFile::SetComments(ODIText* comments)
  1527. {
  1528.     DTPBRec        pb;
  1529.     OSErr        err = noErr;    // PBDTGetPath seems not to return anything,
  1530.                                 // so must init
  1531.     
  1532.     if (comments) // <eeh> --> prevents removing 'em: && GetITextStringLength(comments) > 0)
  1533.     {
  1534.         pb.ioNamePtr = kODNULL;
  1535.         pb.ioVRefNum = fFileSpec.vRefNum;
  1536.         err = PBDTGetPath(&pb);
  1537.         if (err == noErr)
  1538.         {
  1539.             pb.ioNamePtr = fFileSpec.name;
  1540.             pb.ioDirID = fFileSpec.parID;
  1541.             pb.ioDTBuffer = GetITextPtr(comments);
  1542.             pb.ioDTReqCount = GetITextStringLength(comments);
  1543.             // avoid the crash on 68K if the PlatformFile is remote
  1544. #if GENERATING68K && GENERATINGCFM
  1545.             err = PBDTSetCommentSyncGlue(&pb);
  1546. #else
  1547.             err = PBDTSetCommentSync(&pb);
  1548. #endif
  1549.         }
  1550.     }
  1551. }
  1552.  
  1553. //------------------------------------------------------------------------------
  1554. // PlatformFile::GetCustomIconFamily
  1555. //------------------------------------------------------------------------------
  1556.  
  1557. ODIconFamily
  1558. PlatformFile::GetCustomIconFamily()
  1559. {
  1560.     ODIconFamily icons = kODNULL;
  1561.     
  1562.     if (HasCustomIcon())
  1563.     {
  1564.         // read icons from the file
  1565.         SetPermission(fsRdPerm);
  1566.         OpenResFile();
  1567.         TRY
  1568.             for( long i=5; i>=0; i-- )
  1569.             {
  1570.                 ODPtr    ptr;
  1571.                 Handle    icon;
  1572.                 ODULong    size;
  1573.                 
  1574.                 ptr = ReadResourcePtr(kIconType[i], kCustomIconResource, &size);
  1575.                 if (ptr != kODNULL)
  1576.                 {
  1577.                     if (icons == kODNULL)
  1578.                         THROW_IF_ERROR( NewIconSuite(&icons) );
  1579.                     PtrToHand(ptr, &icon, size);
  1580.                     THROW_IF_ERROR( AddIconToSuite(icon, icons, kIconType[i]) );
  1581.                 }
  1582.             }
  1583.         CATCH_ALL
  1584.         ENDTRY
  1585.         CloseResFile();
  1586.     }
  1587.     return icons;
  1588. }
  1589.  
  1590. //------------------------------------------------------------------------------
  1591. // PlatformFile::SetCustomIconFamily
  1592. //------------------------------------------------------------------------------
  1593.  
  1594. void
  1595. PlatformFile::SetCustomIconFamily(ODIconFamily icons)
  1596. {
  1597.     // set with kODNULL as the icons to delete the custom icons
  1598.     TRY
  1599.         if (!icons)
  1600.         {
  1601.             // check to see if there's a resFile so that we don't
  1602.             // create one while trying to delete nonexistant icons
  1603.             SetPermission(fsRdPerm);
  1604.             OpenResFile();        // THROW if no resFile
  1605.             CloseResFile();
  1606.         }
  1607.         // write icons to the file
  1608.         SetPermission(fsRdWrPerm);
  1609.         OpenResFile();
  1610.         for( long i=5; i>=0; i-- )
  1611.         {
  1612.             Handle    icon;
  1613.             char    state;
  1614.             
  1615.             if( icons )
  1616.                 THROW_IF_ERROR( GetIconFromSuite(&icon, icons, kIconType[i]) );
  1617.             else
  1618.                 icon = kODNULL;
  1619.             if (icon)
  1620.             {
  1621.                 state = HGetState(icon);
  1622.                 HLock(icon);
  1623.                 WASSERT(GetHandleSize(icon) == kIconSize[i]);
  1624.                 WriteResourcePtr(kIconType[i], kCustomIconResource, *icon, kIconSize[i]);
  1625.                 HSetState(icon, state);
  1626.             } else
  1627.                 DeleteResource(kIconType[i], kCustomIconResource);
  1628.         }
  1629.         CloseResFile();
  1630.     CATCH_ALL
  1631.     ENDTRY
  1632.     SetCustomIcon(icons != kODNULL);
  1633. }
  1634.